using System;
using System.Collections.Generic;
using System.Text;

namespace CoreCalc.SheetDefinedFunctions.CompOnlyNeededCells
{
    public class Condition
    {
        private bool shouldAlwaysBeevaluated;
        private bool shouldAlwaysBeevaluatedSuper;
        private ConditionTreeNode conditionRoot;

        public ConditionTreeNode ConditionRoot
        {
            get { return conditionRoot; }
        }

        public bool ShouldAlwaysBeevaluated
        {
            get { return shouldAlwaysBeevaluated; }
        }

        public bool ShouldAlwaysBeevaluatedSuper
        {
            get { return shouldAlwaysBeevaluatedSuper; }
            set 
            { 
                shouldAlwaysBeevaluatedSuper = value;
                if (value)
                    shouldAlwaysBeevaluated = true;
            }
        }

        public Condition(CGExpr expression, bool expressionNeedToBeTrue)
        {
            this.shouldAlwaysBeevaluated = false;
            conditionRoot = new ConditionTreeLeaf(expression, expressionNeedToBeTrue);
            shouldAlwaysBeevaluatedSuper = false;
        }

        public Condition()
        {
            this.shouldAlwaysBeevaluated = true;
            conditionRoot = null;
            shouldAlwaysBeevaluatedSuper = false;
        }

        public void And(Condition other)
        {
            if(shouldAlwaysBeevaluatedSuper || other.shouldAlwaysBeevaluatedSuper)
            {
                this.shouldAlwaysBeevaluatedSuper = true;
                shouldAlwaysBeevaluated = true;
                conditionRoot = null;
            }
            if (ShouldAlwaysBeevaluated && other.ShouldAlwaysBeevaluated)
            {
                this.shouldAlwaysBeevaluated = true;
                conditionRoot = null;
            }
            else if(ShouldAlwaysBeevaluated)
            {
                shouldAlwaysBeevaluated = false;
                conditionRoot = other.ConditionRoot;
            }
            else if(!other.ShouldAlwaysBeevaluated)
            {
                conditionRoot = new ConditionTreeNodeAnd(ConditionRoot, other.ConditionRoot);
            }
            //the last else (other.shouldAlwaysBeevaluated == true) is equal to doing nothing)
        }

        public void Or(Condition other)
        {
            if (ShouldAlwaysBeevaluated || other.ShouldAlwaysBeevaluated)
            {
                this.shouldAlwaysBeevaluated = true;
                conditionRoot = null;
            }
            else 
            {
                ConditionTreeLeaf thisLeaf = ConditionRoot as ConditionTreeLeaf;
                ConditionTreeLeaf otherLeaf = other.ConditionRoot as ConditionTreeLeaf;
                if(thisLeaf != null && otherLeaf != null && thisLeaf.Expression == otherLeaf.Expression)
                {
                    if(thisLeaf.ShouldBeTrue != otherLeaf.ShouldBeTrue)
                    {
                        conditionRoot = null;
                        shouldAlwaysBeevaluated = true;
                    }
                    //else do nothing (if the two leafs have the same condition only one is needed => do nothing)
                }
                else
                    conditionRoot = new ConditionTreeNodeOr(ConditionRoot, other.ConditionRoot);
            }
        }
    }
}
